// ============================================================================
//
// Graph framework by Aurelien Moreau aurelien.moreau@gmail.com
// Modified by Pierre CHATEL chatelp@gmail.com
// Distributed under LGPL
// Copyright (C) Aurelien Moreau, 2008, 2009. All rights reserved
//
// ============================================================================

package com.thalesgroup.graphFramework.core.impl;

import java.util.ArrayList;

import com.thalesgroup.graphFramework.core.Graph;
import com.thalesgroup.graphFramework.core.GraphBuilder;
import com.thalesgroup.graphFramework.core.Vertex;


public class GraphBuilderImpl<V, E> implements GraphBuilder<V, E> {

	protected GraphImpl<V, E> graph;

	protected boolean isFinalized;
	
	protected ArrayList<VertexImpl<V,E>> vertices;
	protected ArrayList<EdgeImpl<V,E>> edges;

	public GraphBuilderImpl() {
		vertices=new ArrayList<VertexImpl<V,E>>();
		edges=new ArrayList<EdgeImpl<V,E>>();
	}
	
	public GraphBuilderImpl(GraphBuilderImpl<V, E> source) {
		if(source.isFinalized)
			throw new RuntimeException("Cannot clone a finalized graph builder");
		
		vertices=new ArrayList<VertexImpl<V,E>>();
		edges=new ArrayList<EdgeImpl<V,E>>();
		
		for (VertexImpl<V,E> vertex : source.vertices) {
			//vertices.add(vertex.clone());
		}
	}
	
	public void createNewGraph() {
		graph = new GraphImpl<V, E>();
		isFinalized = false;
	}

	public void finalizeGraph() {
		
		VertexImpl<V,E>[] vertices_=new VertexImpl[vertices.size()];
		EdgeImpl<V,E>[] edges_=new EdgeImpl[edges.size()];
		
		vertices_=vertices.toArray(vertices_);
		edges_=edges.toArray(edges_);
		
		graph.finalizeGraph(vertices_, edges_);
		isFinalized = true;
		vertices.clear();
		edges.clear();
	}

	public Graph<V, E> getCurrentGraph() {
		assert (isFinalized); // TODO finalize graph
		return graph;
	}

	public EdgeImpl<V, E> createEdge(final Vertex<V, E> src,
			final Vertex<V, E> tgt) {
		return createEdge(src, tgt, null);
	}

	public EdgeImpl<V, E> createEdge(final Vertex<V, E> src,
			final Vertex<V, E> tgt, final E data) {
		if(src ==null) throw new NullPointerException("Null source vertex");
		if(tgt ==null) throw new NullPointerException("Null target vertex");
		if (src.getGraph() != graph) {
			throw new BadGraph(graph, src.getGraph());
		}
		if (tgt.getGraph() != graph) {
			throw new BadGraph(graph, tgt.getGraph());
		}
		final VertexImpl<V, E> srcImpl = (VertexImpl<V, E>) src;
		final VertexImpl<V, E> tgtImpl = (VertexImpl<V, E>) tgt;
		final EdgeImpl<V, E> e = new EdgeImpl<V, E>(graph, edges.size(), srcImpl,
				tgtImpl, data);
		
		srcImpl.outs.add(e);
		tgtImpl.ins.add(e);
		edges.add(e);

		return e;
	}

	public VertexImpl<V, E> createVertex() {
		return createVertex(null);
	}

	public VertexImpl<V, E> createVertex(final V data) {
		final VertexImpl<V, E> vertex = new VertexImpl<V, E>(graph, vertices.size(), data);
		vertices.add(vertex);
		return vertex;
	}

}
